/*
 * Copyright 2015 Ming Xia
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.healthcloud.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.healthcloud.dao.AreaCodeMapper;
import com.healthcloud.entity.AreaCode;
import com.healthcloud.entity.AreaCodeCriteria;
import com.healthcloud.entity.Condition;
import com.healthcloud.query.CriteriaUtils;
import com.healthcloud.service.AreaCodeService;
import com.healthcloud.utils.AreaCodeUtils;
import com.healthcloud.utils.PageParam;

/**
 * @author Sephy
 * @since: 2015-05-13
 */
@Transactional(readOnly = true)
@Service
public class AreaCodeServiceImpl implements AreaCodeService {
	
	public static final AreaCodeCriteria CRITERIA_PROV = new AreaCodeCriteria(null, null,
			AreaCodeUtils.LEVEL_PROVINCE);

	public static final List<Condition<Object>> CRITERIA_PROV_CONDITIONS = CriteriaUtils
			.getConditions(CRITERIA_PROV);

	public static final String TABLE_AREA_CODE = "base_area_code";

	public static final String TABLE_AREA_CODE_EXTRA = "base_area_code_extra";

	@Autowired
	private AreaCodeMapper areaCodeMapper;

	@Override
	public List<AreaCode> getProvinceList() {
		return areaCodeMapper.searchFromTable(CRITERIA_PROV_CONDITIONS, TABLE_AREA_CODE);
	}

	@Override
	public List<AreaCode> getAreaList(Long code) {
		if (code == null) {
			return this.getProvinceList();
		}
		int level = AreaCodeUtils.getNextCodeLevel(code);
		Long[] range = AreaCodeUtils.getAreaRange(code);
		AreaCodeCriteria codeCriteria = new AreaCodeCriteria(range[0], range[1], level);
		if (level == 5) {
			return areaCodeMapper.searchFromTable(CriteriaUtils.getConditions(codeCriteria),
					TABLE_AREA_CODE_EXTRA);
		}
		else {
			return areaCodeMapper.searchFromTable(CriteriaUtils.getConditions(codeCriteria),
					TABLE_AREA_CODE);
		}
	}

	@Override
	@Transactional
	public int saveBatch(List<AreaCode> areaCodeList) {
		return areaCodeMapper.saveBatch(areaCodeList);
	}

	@Override
	public int save(AreaCode areaCode) {
		Integer level = areaCode.getLevel();
		areaCode.setCreatedTime(new Date());
		areaCode.setUpdatedTime(new Date());
		if(level==5){
			return areaCodeMapper.save(areaCode,TABLE_AREA_CODE_EXTRA);
		}else if(level==1||level==2||level==3||level==4){
			return areaCodeMapper.save(areaCode,TABLE_AREA_CODE);
		}else{
			throw new IllegalArgumentException("Illegal level: " + level.toString());
		}
	}

	@Override
	public String getFullAreaName(Long code) {
		List<Long> list = AreaCodeUtils.getFullCode(code);
		StringBuilder builder = new StringBuilder();
		for (Long c : list) {
			String table = TABLE_AREA_CODE;
			if (c.toString().length() > 6) {
				table = TABLE_AREA_CODE_EXTRA;
			}
			AreaCode areaCode = areaCodeMapper.findByCode(c, table);
			if (areaCode != null) {
				builder.append(areaCode.getName());
			}
		}
		return builder.toString();
	}

	@Override
	public List<AreaCode> search(AreaCode area, PageParam pageParam) {
		return areaCodeMapper.search(area, pageParam);
	}

	@Override
	public ArrayList<AreaCode> searchAll() {
		return (ArrayList<AreaCode>) areaCodeMapper.searchAll();
	}

	@Override
	public int count(AreaCode area) {
		return areaCodeMapper.count(area);
	}

	/**
	 * 获取下级地区列表
	 * level:0的数据为大区数据
	 * level:1-4的数据为地区数据base_area_code
	 * level:5的数据为地区数据base_area_code_extra
	 *
	 * @param code 地区code
	 * @param level 地区等级
	 * @return
	 */
	@Override
	public List<AreaCode> getLowerAreaList(String code, String level) {
		if (level==null){
			throw new IllegalArgumentException("Illegal level: NULL" );
		}
		code=(code==null)?"":code;
		if(level.equals("5")){
			return null;
		}else if (level.equals("0")){
			if(code.equals("")){
				AreaCode areaCode = new AreaCode();
				areaCode.setLevel(Integer.valueOf(level)+1);
				return areaCodeMapper.findByEntityAll(areaCode);
			}else{
				return areaCodeMapper.getLowerAreaListByLargeAreaCode(code);
			}
		}else if (level.equals("1") || level.equals("2") || level.equals("3")){
//			return areaCodeMapper.getLowerAreaListByCode(code);
			return areaCodeMapper.getLowerAreaListByCodeLevel(code, Integer.valueOf(level));
		}else if (level.equals("4")){
			return areaCodeMapper.getLowerAreaExtraListByCode(code);
		}else{
			throw new IllegalArgumentException("Illegal level: " + level.toString() );
		}
	}

	@Override
	public List<AreaCode> getLowersAreaList(Long code, Integer num) {
		int s = 5;
		int level = 0;
		if (code == null) {

		}else{
			level = AreaCodeUtils.getCodeLevel(code);
			if(num == null){
				num = s - level;
			}else if (level + num > s) {
				throw new IllegalArgumentException("num 超出范围");
			}
		}
		return areaCodeMapper.getLowersAreaList(code, level + num);
	}

	/**
	 * 根据主键id修改大区code
	 * @param id 主键id
	 * @param largeAreaCode 大区code
	 * @return
	 */
	@Override
	public int updateLargeAreaCodeById(String id, String largeAreaCode){
		return areaCodeMapper.updateLargeAreaCodeById(id, largeAreaCode);
	}

	/**
	 * 根据code获取所有地区极品的列表 大区除外
	 */
	@Override
	public Map<String, List<AreaCode>> getAreaListAll(String code) {
		Map<String, List<AreaCode>> map = new HashMap<>();
		List<AreaCode> provinceList = new ArrayList<>();//省列表
		List<AreaCode> cityList = new ArrayList<>();//市列表
		List<AreaCode> countyList = new ArrayList<>();//县列表
		List<AreaCode> townList = new ArrayList<>();//镇列表
		List<AreaCode> villageList = new ArrayList<>();//村列表

		if (code==null) {
			map.put("1",provinceList);
			map.put("2",cityList);
			map.put("3",countyList);
			map.put("4",townList);
			map.put("5",villageList);
			return map;
		}
		if (code.trim().length()>=2) {
			String provinceCode = code.substring(0,2);
			//根据areaCode获取largeAreaCode
			AreaCode areaCode = new AreaCode();
			areaCode.setCode(Long.valueOf(provinceCode));
			List<AreaCode> areaCodeList = areaCodeMapper.findByEntityAll(areaCode);
			String largeAreaCode = areaCodeList.get(0).getLargeAreaCode();
			//根据largeAreaCode查询一个大区的省级列表
			provinceList = areaCodeMapper.getLowerAreaListByLargeAreaCode(largeAreaCode);

			cityList = areaCodeMapper.getLowerAreaListByCode(provinceCode);
		}
		if (code.trim().length()>=4) {
			String cityeCode = code.substring(0,4);
			countyList = areaCodeMapper.getLowerAreaListByCode(cityeCode);
		}
		if (code.trim().length()>=6) {
			String countyCode = code.substring(0,6);
			townList = areaCodeMapper.getLowerAreaListByCode(countyCode);
		}
		if (code.trim().length()>=9) {
			String townCode = code.substring(0,9);
			villageList = areaCodeMapper.getLowerAreaExtraListByCode(townCode);
		}
		map.put("1",provinceList);
		map.put("2",cityList);
		map.put("3",countyList);
		map.put("4",townList);
		map.put("5",villageList);
		return map;
	}

	@Override
	public List<AreaCode> findByEntityAll(AreaCode entity) {
		return areaCodeMapper.findByEntityAll(entity);
	}

	@Override
	public void setLargeAreaCodeNull(String largeAreaCode) {
		areaCodeMapper.setLargeAreaCodeNull(largeAreaCode);
	}

	@Override
	public String getSomeProvinceAreaForSql(String fieldName, List<AreaCode> provinceList) {
//		String sqlLite="(";
		String sqlLite="";
		if(provinceList.size()==0){
			return sqlLite+fieldName+" LIKE \"0%\")";
		}
		for (int i = 0; i < provinceList.size(); i++) {
//			sqlLite= sqlLite+fieldName+" LIKE \""+provinceList.get(i).getCode()+"%\" OR ";
			sqlLite= sqlLite+fieldName+" like \'"+provinceList.get(i).getCode()+"%\' OR ";
//			sqlLite= sqlLite+fieldName+" LIKE CONCAT('"+provinceList.get(i).getCode()+"','%' ) OR ";

		}
//		sqlLite = sqlLite.substring(0,sqlLite.length()-3)+")";
		sqlLite = sqlLite.substring(0,sqlLite.length()-3);
		return sqlLite;
	}

	@Override
	public List<AreaCode[]> getAreaForLevelList(Long code, Integer num) {
		List<AreaCode[]> acArrList = new ArrayList<>();
		int s = 5;
		int level = 0;
		if (code == null) {

		} else {
			level = AreaCodeUtils.getCodeLevel(code);
			if (num == null) {
				num = s - level;
			} else if (level + num > s) {
				throw new IllegalArgumentException("num 超出范围");
			}
		}

		AreaCode[] acArr = new AreaCode[num + 1];

		List<AreaCode> acList = getLowersAreaList(code, num);

		int lastLevel = -1;//上一个AreaCode的等级
		for (int i = 0; i < acList.size(); i++) {
			AreaCode ac = acList.get(i);
			acArr[ac.getLevel() - level] = ac;
			if (lastLevel <= ac.getLevel()) {
				if(i+1<acList.size()){
					int nextLevel = acList.get(i+1).getLevel();//下一个AreaCode的等级
					if(nextLevel <= ac.getLevel()){
						AreaCode[] acArr1 = new AreaCode[num + 1];
						for (int j = 0; j < acArr1.length; j++) {
							acArr1[j] = acArr[j];
						}
						acArrList.add(acArr1);
					}
				}else{
					AreaCode[] acArr1 = new AreaCode[num + 1];
					for (int j = 0; j < acArr1.length; j++) {
						acArr1[j] = acArr[j];
					}
					acArrList.add(acArr1);
				}

			}

			lastLevel = ac.getLevel();
		}
		return acArrList;
	}

	@Override
	public List<AreaCode> findByAreaNameInAreaCode(String areaName, Integer level, String baseAreaCode) {
		return areaCodeMapper.findByAreaNameInAreaCode(areaName, level, baseAreaCode);
	}

	/**
	 * 根据地区名称 获取code
	 * @param areaNameArr 地区名称(名称级别个数不定，但连续并以村名称开始)
	 *                    如：村名称，镇名称，县名称，市名称，省名称
	 *                    	  村名称，镇名称，县名称
	 * @param level areaNameArr中最底层地区等级 （null值 默认为村级别）
	 * @param baseAreaCode 查找地区code范围
	 * */
	public Long getCodeByAreaName(String[] areaNameArr, Integer level, String baseAreaCode) throws Exception {
		Long code = null;
		if (level == null) {
			level = 5;
		}
		List<List<AreaCode>> acListList = new ArrayList<>();
		for (int i = 0; i < areaNameArr.length; i++) {
			if (areaNameArr[i] == null || areaNameArr[i].equals("")) {
				acListList.add(new ArrayList<AreaCode>());
			} else {
				List<AreaCode> acList = this.findByAreaNameInAreaCode(areaNameArr[i], level, baseAreaCode);
				if (acList.size() == 0) {
					throw new Exception("地区名称未找到！");
				}
				acListList.add(acList);
				if (acList != null && acList.size() == 1) {
					break;
				}
			}
			level--;
		}
		for (int i = acListList.size() - 1; i >= 0; i--) {
			List<AreaCode> acList = acListList.get(i);
			if (acList == null || acList.size() == 0) {

			} else if (acList.size() == 1) {
				code = acList.get(0).getCode();
			} else {
				if (code == null) {
					return null;
				} else {
					for (int j = 0; j < acList.size(); j++) {
						if ((acList.get(j).getCode() + "").indexOf(code + "") != -1) {
							code = acList.get(j).getCode();
							break;
						}
					}
				}
			}
		}
		return code;
	}
}
